/*
 * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
 * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
 * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
 * Vestibulum commodo. Ut rhoncus gravida arcu.
 */

package com.mrd.gtimpframe.service.impl;

import com.mrd.base.Jqgrid;
import com.mrd.framework.config.web.json.Result;
import com.mrd.framework.security.config.SecurityConstants;
import com.mrd.framework.ui.filter.SearchRule;
import com.mrd.framework.ui.filter.SearchRuleOption;
import com.mrd.framework.utils.HttpUtils;
import com.mrd.gtimp.business.entity.Declaration;
import com.mrd.gtimp.business.repository.DeclarationDao;
import com.mrd.gtimp.business.service.DeclarationBiz;
import com.mrd.gtimp.business.service.FundFlowBiz;
import com.mrd.gtimp.v2.datalock.DataLockEntity;
import com.mrd.gtimp.v2.datalock.DataLockUtil;
import com.mrd.gtimpframe.entity.DeclaRelastionship;
import com.mrd.gtimpframe.entity.RejectCount;
import com.mrd.gtimpframe.entity.RejectRecord;
import com.mrd.gtimpframe.entity.RejectRecordReasonRef;
import com.mrd.gtimpframe.entity.User;
import com.mrd.gtimpframe.service.DeclaRelastionshipService;
import com.mrd.gtimpframe.service.RejectCountService;
import com.mrd.gtimpframe.service.RejectRecordReasonRefService;
import com.mrd.gtimpframe.service.RejectRecordService;
import com.mrd.gtimpframe.service.RejectService;
import com.mrd.redis.JedisClientClusterImpl;
import com.mrd.util.LoginUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

/**
 * Created by dusy on 2017/7/31.
 */
@EnableTransactionManagement
@Service
public class RejectServiceImpl implements RejectService {
    @Autowired
    private RejectRecordService rejectRecordService;
    @Autowired
    private DeclarationBiz declarationBiz;
    @Autowired
    private DeclarationDao declarationDao;
    @Autowired
    private FundFlowBiz fundFlowBiz;
    @Autowired
    private DeclaRelastionshipService declaRelastionshipService;
    @Autowired
    private RejectCountService rejectCountService;
    @Autowired
    private RejectRecordReasonRefService rejectRecordReasonRefService;
    @Autowired
    private JedisClientClusterImpl jedisClientCluster;
    @Autowired
    private DataLockUtil dataLockUtil;
    private Logger logger = LoggerFactory.getLogger(RejectServiceImpl.class);

    /**
     * 客户申请驳回
     */
    @Override
    @Transactional
    public Result customerApply(String declaId, String applyReasonId, String remark) throws Exception {
        if (((List<Boolean>) selectByDidsInit(declaId).getData()).get(0)) {
            return Result.newFailInstance("已经申请过了");
        }
        String userId = "";
        String userName = "";
        try {
            userId = LoginUtil.getLoginUserId();
            userName = LoginUtil.getLoginUser().getName();
        } catch (Exception e) {
            User user = (User) HttpUtils.getSession().getAttribute(SecurityConstants.NEW_SESSION_USER_NAME);
            userId = user.getuId();
            userName = user.getuName();
        }
        DataLockEntity dataLockEntity = dataLockUtil.getLockInfo(dataLockUtil.getOpaIDByKey(""), declaId);
        if (dataLockEntity != null && !dataLockEntity.getRegUser().contains(userName)) {
            return Result.newFailInstance("审核中，暂时不能进行驳回操作");
        }
        Declaration declaration = declarationBiz.findEntityById(declaId);
        if (declaration == null) {
            return Result.newFailInstance("没有该报关单记录");
        }
        String originalState = declaration.getState();
        if ((Declaration.DeclarationBusinessState.REJECT_STATE + Declaration.DeclarationBusinessState.CUSTOM_CHARGEBACK).contains(declaration.getState())) {
            return Result.newFailInstance("当前状态不能进行驳回");
        }
        //锁定报关单
        jedisClientCluster.set("lock_decla_" + declaId, "1", 30L, TimeUnit.DAYS);
        declaration.setLockStatus("1");
        declarationBiz.saveOrupdateEntity(declaration);
        //创建驳回记录RECORD0，驳回发起人= User0.ID；驳回发起角色=CUSTOMER；发起时间=new date；报关单ID=D0.ID。
        RejectRecord rejectRecord = new RejectRecord(declaId, "CUSTOMER", userId, remark);
        rejectRecordService.insertSelective(rejectRecord);
        //根据applyReasonId和RECORD0.ID建立驳回记录与驳回原因的联系。
        rejectRecordReasonRefService.insertSelective(new RejectRecordReasonRef(applyReasonId, rejectRecord.getId(), userId));
        //记录驳回次数
        recordRejectCount(declaId, userId);
        //假如state等于DS01，则表示驳回流程在客户这里结束，并执行退款流程。
        if (Declaration.DeclarationBusinessState.ORDER_STATE.equals(originalState)) {
            //执行退款流程
            fundFlowBiz.declarationRefund(declaration);
            //更新驳回记录，驳回受理人= User0.ID，受理时间=new date，受理结果=ACCEPTED。
            rejectRecord.setAcceptor(userId);
            rejectRecord.setAcceptedTime(new Date());
            rejectRecord.setAcceptedResult("ACCEPTED");
            rejectRecordService.updateByPrimaryKeySelective(rejectRecord);
            declaration.setState(Declaration.DeclarationBusinessState.REJECT_STATE);//将D0.state改为DS03，
            declaration.setLockStatus("0");//解锁
            declarationBiz.saveOrupdateEntity(declaration);
            jedisClientCluster.delete("lock_decla_" + declaId);
            return Result.newSuccessInstance("已成功驳回");
        } else { //假如state不等于DS01，则表示驳回申请需要供应商处理。
            return Result.newSuccessInstance("申请完成");
        }
    }

    /**
     * 供应商处理驳回申请
     */
    @Override
    @Transactional
    public Result supplierAccept(String declaId, String acceptedResult, String dealWithNpReason, String acceptedOpinion) throws Exception {
        Declaration declaration = declarationBiz.findEntityById(declaId);
        if (declaration == null) {
            return Result.newFailInstance("没有该报关单记录");
        }
        String userId = LoginUtil.getLoginUserId();
        RejectRecord params = new RejectRecord();
        params.setDid(declaId);
        params.setAcceptedResult("INITIATED");
        List<RejectRecord> rejectRecords = rejectRecordService.selectSelective(params);
        if (rejectRecords == null || rejectRecords.size() == 0) {
            return Result.newFailInstance("该报关单没有申请或申请已处理完毕");
        }
        //更新驳回记录
        params.setId(rejectRecords.get(0).getId());
        params.setAcceptor(userId);
        params.setAcceptedTime(new Date());
        params.setAcceptedResult(acceptedResult);
        params.setDealWithNpReason(dealWithNpReason);
        params.setAcceptedOpinion(acceptedOpinion);
        rejectRecordService.updateByPrimaryKeySelective(params);
        //判断处理结果
        if ("ACCEPTED".equals(acceptedResult)) {//同意驳回: 执行退款流程并更新报关单状态为驳回
            declaration.setState(Declaration.DeclarationBusinessState.REJECT_STATE);//更新报关单状态为驳回
            fundFlowBiz.declarationRefund(declaration);//执行退款流程
        } else {
            DeclaRelastionship declaRelastionship = new DeclaRelastionship(declaration.getId());
            declaRelastionship.setNode(declaration.getId());
            declaRelastionship.setParent(null);//不为空时即从新提交了。
            declaRelastionshipService.insertSelective(declaRelastionship);
        }
        // 解锁报关单
        jedisClientCluster.delete("lock_decla_" + declaId);
        declaration.setLockStatus("0");
        declarationDao.saveOrupdate(declaration);
        return Result.newSuccessInstance("处理成功");
    }

    /**
     * 海关退单
     */
    @Override
    @Transactional
    public Result chargeBack(String declaId, String cbReasonId, String remark) throws Exception {
        if (jedisClientCluster.get("lock_decla_" + declaId, String.class) != null) {
            return Result.newFailInstance("报关单已被锁定，解锁前不能进行操作");
        }
        String userId = LoginUtil.getLoginUserId();
        RejectRecord rejectRecord = new RejectRecord(declaId, "SUPPLIER", userId, remark);
        rejectRecord.setAcceptor(userId);
        rejectRecord.setAcceptedTime(new Date());
        rejectRecord.setAcceptedResult("CHARGEBACK");
        rejectRecordService.insertSelective(rejectRecord);
        rejectRecordReasonRefService.insertSelective(new RejectRecordReasonRef(cbReasonId, rejectRecord.getId(), userId));
        Declaration declaration = declarationBiz.findEntityById(declaId);
        if (declaration == null) {
            return Result.newFailInstance("没有该报关单记录");
        }
        declaration.setState(Declaration.DeclarationBusinessState.CUSTOM_CHARGEBACK);//将state改为DS13，
        declarationDao.saveOrupdate(declaration);
        recordRejectCount(declaration.getId(), userId);
        return Result.newSuccessInstance("退回完成");
    }

    /**
     * 查询客户已申请驳回但未处理的报关单
     */
    @Override
    public Result selectByDidsInit(String declarationIds) {
        if (declarationIds == null) {
            return Result.newFailInstance("参数缺失");
        }
        String[] dids = declarationIds.split(",");
        List<RejectRecord> rejectRecords = rejectRecordService.selectByDidsInit(dids);
        List<Boolean> applied = new ArrayList<Boolean>();
        for (String did : dids) {
            boolean temp = false;
            for (RejectRecord record : rejectRecords) {
                if (did.equals(record.getDid())) {
                    temp = true;
                    break;
                }
            }
            applied.add(temp);
        }
        return Result.newSuccessInstanceUseData(applied);
    }

    @Transactional
    public void recordRejectCount(String declaId, String userId) throws Exception {
        DeclaRelastionship declaRelastionship = declaRelastionshipService.selectByDeclaId(declaId);
        RejectCount rejectCount = rejectCountService.selectByPrimaryKey(declaId);
        if (declaRelastionship == null && rejectCount == null) {//如查询无结果，说明是第一次驳回，
            //创建驳回次数记录
            rejectCount = new RejectCount();
            rejectCount.setId(declaId);
            rejectCount.setDid(declaId);
            rejectCount.setCount(new Short("1"));
            rejectCount.setCreator(userId);
            rejectCount.setCreateTime(new Date());
            rejectCountService.insertSelective(rejectCount);
        } else {//如有查询结果，说明是第n次驳回，取得创建时间最新的记录DECLA_REF0
            //更新驳回次数记录，条件：祖辈ID=D0.ID，更新内容：次数=原次数+1，修改人=User0.ID，修改时间=new date。
            String rejectCountId = declaId;
            if (declaRelastionship != null) {
                rejectCountId = declaRelastionship.getId();
            }
            if (rejectCount == null) {
                rejectCount = rejectCountService.selectByPrimaryKey(rejectCountId);
            }
            rejectCount.setCount((short) (rejectCount.getCount() + 1));
            rejectCount.setModifier(userId);
            rejectCount.setModifyTime(new Date());
            rejectCountService.updateByPrimaryKeySelective(rejectCount);
        }
    }

    /**
     * 供应商驳回
     */
    @Override
    @Transactional
    public Result supplierReject(String declaId, String applyReasonId, String remark) throws Exception {
        if (jedisClientCluster.get("lock_decla_" + declaId, String.class) != null) {
            return Result.newFailInstance("报关单已被锁定，解锁前不能进行操作");
        }
        String userId = LoginUtil.getLoginUserId();
        Declaration declaration = declarationBiz.findEntityById(declaId);
        if (declaration == null) {
            return Result.newFailInstance("没有该报关单记录");
        }
        if ((Declaration.DeclarationBusinessState.REJECT_STATE + Declaration.DeclarationBusinessState.CUSTOM_CHARGEBACK).contains(declaration.getState())) {
            return Result.newFailInstance("当前状态不能进行驳回");
        }
        RejectRecord rejectRecord = new RejectRecord(declaId, "SUPPLIER", userId, remark);
        rejectRecord.setAcceptedResult("ACCEPTED");
        rejectRecord.setAcceptor(userId);
        rejectRecord.setAcceptedTime(new Date());
        rejectRecordService.insertSelective(rejectRecord);
        //根据applyReasonId和RECORD0.ID建立驳回记录与驳回原因的联系。
        rejectRecordReasonRefService.insertSelective(new RejectRecordReasonRef(applyReasonId, rejectRecord.getId(), userId));
        declaration.setState(Declaration.DeclarationBusinessState.REJECT_STATE);
        declarationDao.saveOrupdate(declaration);
        recordRejectCount(declaration.getId(), userId);
        fundFlowBiz.declarationRefund(declaration);//执行退款流程
        return Result.newSuccessInstance("驳回完成");
    }

    /**
     * 查询客户报关单驳回情况
     */
    @Override
    public Result rejectRecord(String declarationIds) {
        if (declarationIds == null) {
            return Result.newFailInstance("参数缺失");
        }
        Jqgrid jqgrid = new Jqgrid();
        jqgrid.addRule(new SearchRule("T_BIZ_DECLARATION.ID", SearchRuleOption.in, declarationIds));
        Map<String, String> propertyMap = new HashMap<>();
        //添加查询条件
        propertyMap.put("whereCase", jqgrid.getWhereCase());
        List<RejectRecord> rejectRecords = rejectRecordService.selectByWhereCase(propertyMap);
        Map<String, RejectRecord> rejectRecordMap = new HashMap<>();
        List<RejectRecord> rejectRecordList = new ArrayList<>();
        for (RejectRecord rejectRecord : rejectRecords) {
            RejectRecord mapRecord = rejectRecordMap.get(rejectRecord.getDid());
            if (mapRecord == null || mapRecord.getInitiatedTime().getTime() < rejectRecord.getInitiatedTime().getTime()) {
                rejectRecordMap.put(rejectRecord.getDid(), rejectRecord);
            }
        }
        for (String did : declarationIds.split(",")) {
            rejectRecordList.add(rejectRecordMap.get(did));
        }
        return Result.newSuccessInstance("", rejectRecordList);
    }
}
